﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace theRift
{
    public class GameScene : Microsoft.Xna.Framework.DrawableGameComponent
    {
        // Child game components list
        private readonly List<GameComponent> components;
        
        // Essential services for game scenes
        protected GraphicsDeviceManager graphics;
        protected SpriteBatch spriteBatch;
        protected ModelManager modelManager;
        protected CameraManager cameraManager;
        protected LightManager lightManager;
        protected InputState inputState;
        protected GUI gui;

        // Components of game scene
        public List<GameComponent> Components
        {
            get { return components; }
        }

        // Constructor
        public GameScene(Game game)
            : base(game)
        {
            components = new List<GameComponent>();
            Visible = false;
            Enabled = false;

            Initialize();
        }

        public override void Initialize()
        {
            // Grab global services
            graphics = (GraphicsDeviceManager)Game.Services.GetService(typeof(IGraphicsDeviceManager));
            spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            cameraManager = Game.Services.GetService(typeof(CameraManager)) as CameraManager;
            lightManager = Game.Services.GetService(typeof(LightManager)) as LightManager;
            gui = (GUI)Game.Services.GetService(typeof(GUI));
            inputState = (InputState)Game.Services.GetService(typeof(InputState));

            #region Error Handling

            if (graphics == null)
                throw new InvalidOperationException(Error.NO_GRAPHICSDEVICEMANAGER);

            if (spriteBatch == null)
                throw new InvalidOperationException(Error.NO_SPRITEBATCH);

            if (cameraManager == null)
                throw new InvalidOperationException(Error.NO_CAMERAMANAGER);

            if (lightManager == null)
                throw new InvalidOperationException(Error.NO_LIGHTMANAGER);

            if (gui == null)
                throw new InvalidOperationException(Error.NO_GUI);

            if (inputState == null)
                throw new InvalidOperationException(Error.NO_INPUT);

            #endregion

            base.Initialize();
        }

        // Display scene
        public virtual void Show()
        {
            Visible = true;
            Enabled = true;
        }

        // Hide scene
        public virtual void Hide()
        {
            Visible = false;
            Enabled = false;
        }

        // Update gamecomponent
        public override void Update(GameTime gameTime)
        {
            // Loop through components and update if active
            for (int i = 0; i < components.Count; i++)
            {
                GameComponent gc = components[i];

                if (gc.Enabled)
                {
                    gc.Update(gameTime);
                }
            }

            base.Update(gameTime);
        }

        // Draw component
        public override void Draw(GameTime gameTime)
        {
            for (int i = 0; i < components.Count; i++)
            {
                GameComponent gc = components[i];

                if ((gc is DrawableGameComponent) && ((DrawableGameComponent)gc).Visible)
                {
                    ((DrawableGameComponent)gc).Draw(gameTime);
                }
            }

            base.Draw(gameTime);
        }
    }
}
